﻿using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
using Microsoft.Lync.Model.Group;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading; ////
using System.Windows.Forms;

namespace WindowsFormDemo
{
    public partial class LyncHomeForm : Form
    {
        #region "グローバル変数"

        /// <summary>
        /// Lyncクライアント
        /// </summary>
        Microsoft.Lync.Model.LyncClient _LyncClient;

        /// <summary>
        /// カンバセーション
        /// </summary>
        Conversation _conversation;

        /// <summary>
        /// 選択した連絡先情報取得
        /// </summary>
        Dictionary<string, Contact> _selectedContacts = new Dictionary<string, Contact>();

        /// <summary>
        /// サインインクラス
        /// </summary>
        UserSignIn _userSignIn;

        /// <summary>
        /// 会話の履歴を保存するアレイリスト
        /// </summary>
        private ArrayList _ConversationHistory;

        /// <summary>
        /// メッセージと送信先取得
        /// </summary>
        private StringBuilder _ConversationHistoryHtml;

        /// <summary>
        /// アカウントUri
        /// </summary>
        string _UserUri;

        /// <summary>
        /// メッセージのフォマット
        /// </summary>
        IDictionary<InstantMessageContentType, string> messageDictionary;

        /// <summary>
        /// メッセージのモダリティ
        /// </summary>
        private InstantMessageModality _RemoteIMModality;

        /// <summary>
        /// オーディオカンバセーションウィンドウ
        /// </summary>
        private Dictionary<Conversation, ConversationWindow> conversationWindows = new Dictionary<Conversation, ConversationWindow>();

        /// <summary>
        /// イベントが発生したことを待機中のスレッドに通知します。
        /// </summary>
        private AutoResetEvent conversationWindowLock = new AutoResetEvent(false);

        /// <summary>
        /// Lyncのコンタクトマネージャー
        /// </summary>
        private ContactManager _LyncContactManager;

        /// <summary>
        /// メッセージ送信ボタンとオーディオカンバセーションボタンのフラグ
        /// </summary>
        string _buttonFlag;

        #endregion

        #region "フォームロード"

        public LyncHomeForm()
        {
            InitializeComponent();
        }

        private void LyncHomeForm_Load(object sender, EventArgs e)
        {
            _buttonFlag = string.Empty;
            _LyncClient = LyncClient.GetClient();
            _LyncContactManager = _LyncClient.ContactManager;
            _ConversationHistory = null;
            
            //******************************************************************************
            //インスタントメッセージの履歴を表示するため、アレイリストを作成します。
            //******************************************************************************
            _ConversationHistory = new ArrayList();

            //******************************************************************************
            //カンバセーションがNullの場合
            //******************************************************************************
            if (_conversation == null)
            {
                 Message_TextBox.Text = string.Empty;
                _ConversationHistoryHtml = new StringBuilder();
            }

            if (_LyncClient == null)
            {
                throw new Exception("Lyncクライアントに接続できません。");
            }

            _userSignIn = new UserSignIn();
            _userSignIn.CloseAppConditionHit += _userSignIn_CloseAppConditionHit;
            _userSignIn.UserIsSignedIn += _userSignIn_UserIsSignedIn;
            _userSignIn.SetWindowCursor += _userSignIn_SetWindowCursor;
            _userSignIn.ClientStateChanged += _userSignIn_ClientStateChanged;

            _LyncClient.ConversationManager.ConversationAdded += ConversationManager_ConversationAdded;
            _LyncClient.ConversationManager.ConversationRemoved += ConversationManager_ConversationRemoved;
        }

        private void LyncHomeForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                //画面を閉じる時、Lyncクライアントからサインアウトする
                if (_LyncClient.InSuppressedMode == true)
                {
                    if (_LyncClient.State == ClientState.SignedIn)
                    {
                        EndConversation();
                        _LyncClient.BeginSignOut((ar) => { _LyncClient.EndSignOut(ar); }, null);
                        UserName_Label.Text = string.Empty;
                        
                        this.Invoke(new ClearAllContactsDelegate(ClearAllContacts));
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Send_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { End_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Add_Delete_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Conversation_Button, false });
                    }
                }
            }
            catch (LyncClientException)
            {
            }
        }

        #endregion

        #region "サインインメソッド"

        void _userSignIn_ClientStateChanged(string newState)
        {
            this.Invoke(new ChangeLabelTextDelegate(ChangeLabelText), new object[] { ClientStateString_Label, newState });
            if (newState == ClientState.SigningOut.ToString())
            {
                _userSignIn.ClientStateChanged -= _userSignIn_ClientStateChanged;
            }
        }

        void _userSignIn_SetWindowCursor(Cursor newCursor)
        {
            this.Invoke(new SetCursorForUserDelegate(SetCursorForUser), new object[] { newCursor });
        }

        void _userSignIn_UserIsSignedIn(LyncClient lyncClient)
        {
            _LyncClient = lyncClient;
           
            this.Invoke(new NoParamDelegate(LoadAllContacts));
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Send_Button, true });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { End_Button, true });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Add_Delete_Button, true });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Conversation_Button, true });
            try
            {
                string userName = _LyncClient.Self.Contact.GetContactInformation(ContactInformationType.DisplayName).ToString();
                this.Invoke(new UpdateControlContentDelegate(UpdateControlContent), new object[] { UserName_Label, userName });
            }
            catch (NullReferenceException)
            {
                this.Invoke(new UpdateControlContentDelegate(UpdateControlContent), new object[] { UserName_Label, "ユーザー名を表示できません。" });
            }
            this.Invoke(new SetCursorForUserDelegate(SetCursorForUser), new object[] { System.Windows.Forms.Cursors.Arrow });
        }

        void _userSignIn_CloseAppConditionHit()
        {
            this.Invoke(new NoParamDelegate(CloseWindow));
        }

        #endregion

        #region "会話マネージャイベントハンドラ"

        /// <summary>
        /// 会話を終了する
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">ConversationManagerEventArgs</param>
        internal void ConversationManager_ConversationRemoved(object sender, ConversationManagerEventArgs e)
        {
            //this.Invoke(new SetContactSelectionModeDelegate(SetContactSelectionMode), new object[] { SelectionMode.One });
            
            this.Invoke(new NoParamDelegate(LoadAllContacts));

            //UIスレッドに実行をポスト
            this.BeginInvoke(new MethodInvoker(delegate()
            {
                //カンバセーションウィンドウが作成したかチェック
                if (conversationWindows.ContainsKey(e.Conversation))
                {
                    //カンバセーションウィンドウを取得する
                    ConversationWindow window = conversationWindows[e.Conversation];

                    //カンバセーションを削除する
                    conversationWindows.Remove(e.Conversation);

                    //ウィンドウを閉じる
                    window.Close();
                    window.Dispose();
                }

            }));
        }

        /// <summary>
        /// 会話マネージャーに接続して会話を開始する
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">ConversationManagerEventArgs</param>
        internal void ConversationManager_ConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
        {
            Boolean addedByThisProcess = true;

            if (_conversation == null)
            {
                addedByThisProcess = false;
                _conversation = e.Conversation;
            }

            if (_buttonFlag.Equals("Audio"))
            {
                //新カンバセーションウィンドウを作成
                ConversationWindow window = new ConversationWindow(e.Conversation, _LyncClient);

                //UIスレッドに実行をポスト
                this.BeginInvoke(new MethodInvoker(delegate()
                {
                    //ウィンドウをDictionaryに追加する
                    conversationWindows.Add(e.Conversation, window);

                    //ウィンドウロードイベントを登録する
                    window.Load += window_Load;

                    //新ウィンドウを表示する
                    window.Show(this);

                }));

                //ウィンドウがSDKのスレッドを解放するためにロードされるまで待機します
                conversationWindowLock.WaitOne();
            }
            else if (_buttonFlag.Equals("Send"))
            {
                e.Conversation.ParticipantAdded += Conversation_ParticipantAdded;

                if (addedByThisProcess == true)
                {
                    foreach (Contact selectedContact in _selectedContacts.Values)
                    {
                        AddContactToConversation(_conversation, selectedContact);
                    }
                }
            }
            //ボタンを有効、無効に設定する
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { End_Button, true });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Send_Button, true });
            
        }

        /// <summary>
        /// カンバセーションウィンドウの読み込みが終わた後Lyncスレッドからのロックを削除。
        /// </summary>
        void window_Load(object sender, EventArgs e)
        {
            //LyncのSDKスレッドを保持するために使用されるロックを解除する
            conversationWindowLock.Set();
        }

        /// <summary>
        /// 会話に参加者を追加する
        /// </summary>
        /// <param name="source">Conversation Source conversation.</param>
        /// <param name="data">ParticpantCollectionEventArgs Event data</param>
        void Conversation_ParticipantAdded(Object source, ParticipantCollectionChangedEventArgs data)
        {

            if (data.Participant.IsSelf == false)
            {
                if (((Conversation)source).Modalities.ContainsKey(ModalityTypes.InstantMessage))
                {
                    _RemoteIMModality = data.Participant.Modalities[ModalityTypes.InstantMessage] as InstantMessageModality;
                    _RemoteIMModality.InstantMessageReceived += myInstantMessageModality_MessageReceived;
                }
            }
        }

        /// <summary>
        /// 連絡先からメッセージを受け取る
        /// </summary>
        /// <param name="source">InstantMessageModality Modality </param>
        /// <param name="data">SendMessageEventArgs The new message.</param>
        void myInstantMessageModality_MessageReceived(Object source, MessageSentEventArgs data)
        {
            //メッセージを取得する
            IDictionary<InstantMessageContentType, string> messageFormatProperty = data.Contents;
            //メッセージの宛先の表示名を取得する
            string Sender = (string)((InstantMessageModality)source).Participant.Contact.GetContactInformation(ContactInformationType.DisplayName);

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            string receivedMessage;
            
            receivedMessage = "<DIV style=\"font-size:" +
                    "10pt;font-family:" +
                    "MS Shell Dlg 2;color: #463939;direction: ltr\">" +
                    data.Text +
                    "</DIV>";
            _ConversationHistory.Add(receivedMessage);

            //****************************************************************
            //会話履歴を保存して表示する
            //****************************************************************
            object[] actionObjectArray = { Sender, _ConversationHistory };
            this.Invoke(new ChangeListContents(SetListContents), new object[] { History_WebBrowser, actionObjectArray });
        }

        #endregion

        #region "デリゲート"
        private delegate void NoParamDelegate();
        private delegate void UpdateControlContentDelegate(object controlToUpdate, string newContent);
        private void UpdateControlContent(object controlToUpdate, string newContent)
        /// <summary>
        /// Lyncクライアントの状況を表示する
        /// </summary>
        /// <param name="cursorToSet">System.Windows.Forms.Cursor</param>
        {
            switch (controlToUpdate.GetType().Name.ToLower())
            {
                case "label":
                    System.Windows.Forms.Label label = (System.Windows.Forms.Label)controlToUpdate;
                    label.Text = newContent;
                    break;
                case "textbox":
                    System.Windows.Forms.TextBox textBox = (System.Windows.Forms.TextBox)controlToUpdate;
                    textBox.Text = newContent;
                    break;
            }
        }

        private delegate void SetCursorForUserDelegate(System.Windows.Forms.Cursor cursorToSet);
        /// <summary>
        /// サインイン中にカーソル表示する
        /// </summary>
        /// <param name="cursorToSet">System.Windows.Forms.Cursor</param>
        private void SetCursorForUser(System.Windows.Forms.Cursor cursorToSet)
        {
            this.Cursor = cursorToSet;
            this.Refresh();

        }

        private delegate void EnableDisableButtonDelegate(Button buttonToUpdate, Boolean newButtonEnableState);
        /// <summary>
        /// ボタンを有効、無効にする
        /// </summary>
        /// <param name="buttonToUpdate"></param>
        /// <param name="newButtonEnableState"></param>
        private void EnableDisableButton(Button buttonToUpdate, Boolean newButtonEnableState)
        {
            buttonToUpdate.Enabled = newButtonEnableState;
        }

        private delegate void ClearAllContactsDelegate();
        /// <summary>
        /// 連絡先リストボックスをクリアする
        /// </summary>
        private void ClearAllContacts()
        {
            Contact_ListBox.Items.Clear();
        }

        private delegate void SetContactSelectionModeDelegate(SelectionMode newMode);
        /// <summary>
        /// 連絡先リストボックスの選択モードを変更する
        /// </summary>
        /// <param name="newMode"></param>
        private void SetContactSelectionMode(SelectionMode newMode)
        {
            Contact_ListBox.SelectionMode = newMode;
        }

        private delegate void ChangeLabelTextDelegate(Label labelToUpdate, string newText);
        /// <summary>
        /// ラベルのテキストを設定する
        /// </summary>
        /// <param name="labelToUpdate">Label</param>
        /// <param name="newText">string</param>
        private void ChangeLabelText(Label labelToUpdate, string newText)
        {
            labelToUpdate.Text = newText;
        }

        private delegate void ChangeListContents(WebBrowser webBrowserToUpdate, object[] actionObjectArray);
        /// <summary>
        /// 会話の履歴を表示する
        /// </summary>
        /// <param name="webBrowserToUpdate">WebBrowser</param>
        /// <param name="actionDataArray">object[]</param>
        private void SetListContents(WebBrowser webBrowserToUpdate, object[] actionDataArray)
        {
            //***************************************************
            //カンバセーション履歴を保存するアレイリスト
            //***************************************************
            ArrayList historyArray = (ArrayList)actionDataArray[1];

            //***************************************************
            //メッセージの送信先名を保存する項目
            //***************************************************
            string sender = (string)actionDataArray[0];


            //***************************************************
            //送信したメッセージテキスト
            //***************************************************
            string receivedMessage = historyArray[historyArray.Count - 1].ToString();

            //***************************************************
            //送信先名、送信したメッセージを表示する
            //***************************************************

            _ConversationHistoryHtml.Insert(0, sender + receivedMessage);
            webBrowserToUpdate.DocumentText = _ConversationHistoryHtml.ToString();

            //***************************************************
            //新しいメッセージ保存ため、履歴アレイをリセットする
            //***************************************************
            string recMessage = sender + ": " + receivedMessage;
            historyArray.RemoveAt(historyArray.Count - 1);
            historyArray.Add(recMessage);
        }

        #endregion

        #region "ボタンイベント"

        /// <summary>
        /// 「連絡先追加/削除」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            ContactUriAdd addContactUri = new ContactUriAdd();
            addContactUri.ShowDialog();
            LoadAllContacts();
        }

        /// <summary>
        /// 「サインイン」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void StartLync_Button_Click(object sender, EventArgs e)
        {
            ClearAllContacts();
            Send_Button.Enabled = false;
            End_Button.Enabled = false;
            _userSignIn.StartUpLync();
            _LyncClient = _userSignIn.Client;
            ClientStateString_Label.Text = _LyncClient.State.ToString();
            //_LyncClient.ConversationManager.ConversationRemoved += ConversationManager_ConversationRemoved;
        }

        /// <summary>
        /// 「サインアウト」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void StopLync_Button_Click(object sender, EventArgs e)
        {
            try
            {
                if (_LyncClient.InSuppressedMode == true)
                {
                    if (_LyncClient.State == ClientState.SignedIn)
                    {
                        EndConversation();
                        _LyncClient.BeginSignOut((ar) => { _LyncClient.EndSignOut(ar); }, null);
                        UserName_Label.Text = string.Empty;
                        //Clear out the contact list on the UI to be replaced with only the contacts selected for the current conversation.
                        this.Invoke(new ClearAllContactsDelegate(ClearAllContacts));
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Send_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { End_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Add_Delete_Button, false });
                        this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Conversation_Button, false });
                    }
                }
            }
            catch (LyncClientException)
            {
            }
        }

        /// <summary>
        /// 「送信」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void Send_Button_Click(object sender, EventArgs e)
        {
            _buttonFlag = "Send";
            _conversation = null;
            if (_conversation == null)
            {

                if (Contact_ListBox.SelectedItems == null)
                {
                    MessageBox.Show("連絡先を選択してください。");
                    return;
                }
                _selectedContacts.Clear();
                foreach (Object selectedObject in Contact_ListBox.SelectedItems)
                {
                    _selectedContacts.Add(selectedObject.ToString(), _LyncClient.ContactManager.GetContactByUri(selectedObject.ToString()));
                    //if (!_selectedContacts.ContainsKey(selectedObject.ToString()))
                    //{
                    //    _selectedContacts.Add(selectedObject.ToString(), _LyncClient.ContactManager.GetContactByUri(selectedObject.ToString()));
                    //}
                }
                //_LyncClient.ConversationManager.ConversationAdded += new EventHandler<ConversationManagerEventArgs>(ConversationManager_ConversationAdded);
                
                //_LyncClient.ConversationManager.ConversationAdded += ConversationManager_ConversationAdded;
                _conversation = _LyncClient.ConversationManager.AddConversation();
            }
            
            //***********************************************************
            //送信するメッセージがない時、操作が終わってリターンする
            //***********************************************************
            if (Message_TextBox.Text.Length == 0)
            {
                return;
            }
            try
            {
                string messageString = Message_TextBox.Text;
                //*************************************************************
                //メッセージテキストボックスに入力したメッセージをLyncクライアント
                //から読み込めるHTMLフォマットに変更する
                //*************************************************************
                string FormattedMessage = "<DIV style=\"font-size:"
                    + Message_TextBox.Font
                    + "pt;font-family:"
                    + Message_TextBox.Font.ToString()
                    + ";color: #463939;direction: ltr\">"
                    + messageString
                    + "</DIV>";

                //*************************************************************
                //HTMLキーとHTMLテキストをDictionary中に保存する
                //*************************************************************
                messageDictionary = new Dictionary<InstantMessageContentType, string>();
                messageDictionary.Add(InstantMessageContentType.Html, FormattedMessage);

                //*************************************************************
                //連絡先がオフライン、応答不可になった場合、メッセージを送信
                //することができません。
                //
                //ノート: ネットワークが接続できない状況には、カンバセーションも
                //      　失敗になりますので、ご注意ください。
                //*************************************************************

                if (
                    ((InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage]).CanInvoke(ModalityAction.SendInstantMessage)
                )
                {
                    //*************************************************************
                    //Dictionary中に保存したデータを送信する
                    //*************************************************************
                    ((InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage]).BeginSendMessage(
                        messageDictionary
                        , SendMessageCallback
                        , ((InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage]));

                    string Sender = (string)((InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage]).Participant.Contact.GetContactInformation(ContactInformationType.DisplayName);
                    _ConversationHistory.Add(FormattedMessage);

                    //****************************************************************
                    //メッセージの履歴をウェブペブラウザーに表示する
                    //****************************************************************
                    object[] actionObjectArray = { Sender, _ConversationHistory };
                    //this.Dispatcher.Invoke(_FormActionDelegate, new object[] { FormActions.SetListContents, History_WebBrowser, actionObjectArray });
                    this.Invoke(new ChangeListContents(SetListContents), new object[] { History_WebBrowser, actionObjectArray });

                    Message_TextBox.Text = string.Empty;
                }
                else
                {
                    MessageBox.Show("メッセージを送信できません。 " +
                        ((InstantMessageModality)_conversation.Modalities[ModalityTypes.InstantMessage]).State.ToString(),
                        "メッセージ送信エラー");
                    EndConversation();
                }

            }
            catch (LyncClientException ex)
            {
                MessageBox.Show("メッセージを送信できません。 " +
                        ex.Message,
                        "メッセージ送信エラー");
                EndConversation();
            }
            catch (UnauthorizedAccessException)
            {
                MessageBox.Show("Contact cannot accept instant messages");
                EndConversation();
            }
        }

        /// <summary>
        /// 「カンバセーション終了」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void End_Button_Click(object sender, EventArgs e)
        {
            EndConversation();
        }

        /// <summary>
        /// 「オーディオカンバセーション」ボタンイベント 
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void Conversation_Button_Click(object sender, EventArgs e)
        {
            _buttonFlag = "Audio";
            _conversation = null;
            if (_conversation == null)
            {

                if (Contact_ListBox.SelectedItems == null)
                {
                    MessageBox.Show("連絡先を選択してください。");
                    return;
                }
                
                
                _conversation = _LyncClient.ConversationManager.AddConversation();
            }
            Contact contact = null;

            //連絡先の情報を取得する
            try
            {
                _selectedContacts.Clear();
                foreach (Object selectedObject in Contact_ListBox.SelectedItems)
                {
                    _selectedContacts.Add(selectedObject.ToString(), _LyncClient.ContactManager.GetContactByUri(selectedObject.ToString()));
                    contact = _LyncContactManager.GetContactByUri(selectedObject.ToString());
                }
                
            }
            catch (LyncClientException lyncClientException)
            {
                Console.WriteLine("連絡先が見つかりませんでした." + lyncClientException);
            }
            //連絡先をカンバセーションに追加する
            if (contact != null && _conversation != null)
            {
                try
                {
                    _conversation.AddParticipant(contact);
                }
                catch (LyncClientException lyncClientException)
                {
                    Console.WriteLine(lyncClientException);
                }
                
            }
        }

        #endregion

        #region "プライベート機能"

        /// <summary>
        /// 画面を閉じる
        /// </summary>
        private void CloseWindow()
        {
            this.Close();
        }

        /// <summary>
        /// 会話を終了する
        /// </summary>
        private void EndConversation()
        {
            _buttonFlag = string.Empty;
            Message_TextBox.Text = string.Empty;
            History_WebBrowser.DocumentText = string.Empty;
            if (_conversation == null)
            {
                return;
            }
            if (_conversation.State != ConversationState.Terminated)
            {
                _LyncClient.ConversationManager.ConversationRemoved += ConversationManager_ConversationRemoved;
                _conversation.End();
                _conversation = null;
            }
        }

        /// <summary>
        /// メッセージ送信完了後に、実装する機能
        /// </summary>
        /// <param name="_asyncOperation">IAsyncResult The operation result</param>
        private void SendMessageCallback(IAsyncResult ar)
        {
            if (ar.IsCompleted == true)
            {
                try
                {
                    ((InstantMessageModality)ar.AsyncState).EndSendMessage(ar);
                }
                catch (LyncClientException ex)
                {
                    MessageBox.Show("メッセージを送信できません。 " +
                        ex.Message,
                        "メッセージ送信エラー");
                    EndConversation();
                }
            }
        }

        /// <summary>
        /// 会話に参加者を追加する
        /// </summary>
        /// <param name="pConversation">Conversation</param>
        /// <param name="remoteContact">Contact</param>
        public Boolean AddContactToConversation(Conversation pConversation, Contact remoteContact)
        {
            Boolean returnValue = false;


            if (0 == ((ContactCapabilities)remoteContact.GetContactInformation(ContactInformationType.Capabilities) & ContactCapabilities.RenderInstantMessage))
            {
                //***********************************************************
                //連絡先に会話することができない状況
                //***********************************************************
                return false;
            }


            //***********************************************************
            //連絡先に会話することができない場合、Falseが返す
            //***********************************************************
            if (((ContactAvailability)remoteContact.GetContactInformation(ContactInformationType.Availability)) == ContactAvailability.DoNotDisturb
                || ((ContactAvailability)remoteContact.GetContactInformation(ContactInformationType.Availability)) == ContactAvailability.Offline)
            {
                return false;
            }
            try
            {
                //***********************************************************
                //連絡先に会話できるかの確認
                //***********************************************************
                if (pConversation.CanInvoke(ConversationAction.AddParticipant))
                {

                    //***********************************************************
                    //連絡先を会話に参加させる
                    //***********************************************************
                    pConversation.AddParticipant(remoteContact);

                    returnValue = true;
                }
            }
            catch (ItemAlreadyExistException) { }
            return returnValue;
        }

        /// <summary>
        /// 連絡先リストボックスにLyncクライアントの連絡先を表示する
        /// </summary>
        private void LoadAllContacts()
        {
            //Set the selection mode of the UI list to One-select
            Contact_ListBox.SelectionMode = SelectionMode.One;
            Contact_ListBox.Items.Clear();
            try
            {
                foreach (Group group in _LyncClient.ContactManager.Groups)
                {
                    foreach (Contact contact in group)
                    {
                        if (!Contact_ListBox.Items.Contains(contact.Uri))
                            Contact_ListBox.Items.Add(contact.Uri);
                    }
                }
            }
            catch (LyncClientException lce)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine(
                    System.DateTime.Now.Hour.ToString() +
                    ":" +
                    System.DateTime.Now.Minute.ToString() +
                    ":" +
                    System.DateTime.Now.Second.ToString() +
                    ":" +
                    System.DateTime.Now.Millisecond.ToString() +
                    " LoadAllContacts, Lync Client Exception: " + lce.Message);
#endif
            }
        }

        /// <summary>
        /// Signs a user in to Lync as one of two possible users. User that is
        /// signed in depends on whether side-by-side client is chosen.
        /// </summary>
        private void SignUserIn()
        {
            //Set the display cursor to indicate that user must wait for
            //sign in to complete
            this.Invoke(new SetCursorForUserDelegate(SetCursorForUser), new object[] { System.Windows.Forms.Cursors.WaitCursor });

            //Set the sign in credentials of the user to the
            //appropriate credentials for the endpoint mode
            string userUri = string.Empty;
            string userPassword = string.Empty;


            SignInCreds getCreds;
            getCreds = new SignInCreds("Sign in");
            if (getCreds.ShowDialog() == DialogResult.OK)
            {
                if (getCreds.UserName.Equals(string.Empty))
                {
                    MessageBox.Show("アカウントUriを入力してください。");
                    return;
                }
                else if (getCreds.Password.Equals(string.Empty))
                {
                    MessageBox.Show("アカウントパスワードを入力してください。");
                    return;
                }
                else
                {
                    userUri = getCreds.UserName;
                    userPassword = getCreds.Password;
                    getCreds.Close();
                }
            }

            _UserUri = userUri;

            this.Invoke(new ClearAllContactsDelegate(ClearAllContacts));
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Send_Button, false });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { End_Button, false });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Add_Delete_Button, false });
            this.Invoke(new EnableDisableButtonDelegate(EnableDisableButton), new object[] { Conversation_Button, false });
            this.Invoke(new ChangeLabelTextDelegate(ChangeLabelText), new object[] { ClientStateString_Label, _LyncClient.State.ToString() });



            _LyncClient.BeginSignIn(
                userUri,
                userUri,
                userPassword,
                (ar) =>
                {
                    try
                    {
                        _LyncClient.EndSignIn(ar);

                        this.Invoke(
                            new UpdateControlContentDelegate(UpdateControlContent),
                            new object[] { this.ClientStateString_Label, "Signed in" });
                    }
                    catch (Exception exc)
                    {
                        MessageBox.Show("サインインする時、エラーが発生しました。 " + exc.Message);
                    }
                },
                null);

        }

        #endregion

        #region "リストブックスエベントハンドラ"
        /// <summary>
        /// 連絡先リストボックスの選択変更イベント
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">EventArgs</param>
        private void Contact_ListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            EndConversation();
        }

        #endregion

    }

    /// <summary>
    /// 連絡先情報取得クラス 
    /// </summary>
    /// <param name=""></param>
    public class ContactInfo
    {
        #region "ゲット、セット"
        private string displayName = null;
        public string DisplayName
        {
            get
            {
                if (string.IsNullOrEmpty(displayName))
                {
                    return SipUri;
                }
                else
                {
                    return displayName + " (" + SipUri + ")";
                }
            }
        }

        public string SipUri { get; set; }

        public Contact Contact { get; set; }
        #endregion

        #region "連絡先情報取得機能"
        public ContactInfo(Contact contact)
        {
            this.Contact = contact;
            this.SipUri = contact.Uri;
            displayName = (string)this.Contact.GetContactInformation(ContactInformationType.DisplayName);
        }
        #endregion
    }
}
